#define USE_PDATA_PAGING_REGISTER 0

__sbit __at( 0xF7 ) B_7;
__sbit __at( 0xF6 ) B_6;
__sbit __at( 0xF5 ) B_5;

#if defined DSDCC_MODEL_HUGE
void
_gptrput( char *gptr, char c ) __naked {
  /* This is the banked version with pointers up to 22 bits.
     B cannot be trashed */

  gptr;
  c; /* hush the compiler */

  __asm
  ;
  ;
  depending on the pointer type according to SDCCsymt.h
  ;
  jb      _B_7, codeptr$        ;
  >0x80 code       ;
  3
  jnb     _B_6, xdataptr$       ;
  <0x40 far        ;
  3

  mov     dph, r0 ;
  save r0 independant of regbank ;
  2
  mov     r0, dpl ;
  use only low order address     ;
  2

  jb      _B_5, pdataptr$       ;
  >0x60 pdata      ;
  3
  ;
  ;
  store into near/idata space
  ;
  mov     @r0, a                                   ;
  1
  dataptrrestore$:
  mov     r0, dph ;
  restore r0                     ;
  2
  mov     dph, #0 ; restore dph                    ; 2
  ret                                             ;
  1
  ;
  ;
  cannot store into code space, lock up
  ;
  codeptr$:
  sjmp    .                                       ;
  2
  ;
  ;
  store into external stack/pdata space
  ;
  pdataptr$:
  movx    @r0, a                                   ;
  1
  sjmp    dataptrrestore$                         ;
  2
  ;
  ;
  store into far space
  ;
  xdataptr$:
  mov     _P3, b                                   ;
  3

  movx    @dptr, a                                 ;
  1
  ret                                             ;
  1

  ;
  ===
  ;
  29 bytes
  __endasm;
}

#elif defined DSDCC_MODEL_MEDIUM

void
_gptrput( char *gptr, char c ) __naked {
  /* This is the non-banked version with pointers up to 14 bits.
     Assumes B is free to be used */

  gptr;
  c; /* hush the compiler */

  __asm
  ;
  ;
  depending on the pointer type according to SDCCsymt.h
  ;
  mov     b, dph                                   ;
  3
  jb      _B_7, codeptr$        ;
  >0x80 code       ;
  3
  jnb     _B_6, xdataptr$       ;
  <0x40 far        ;
  3

  mov     b, r0   ;
  save r0 independant of regbank ;
  2
  mov     r0, dpl ;
  use only low order address     ;
  2

  jb      _B_5, pdataptr$       ;
  >0x60 pdata      ;
  3
  ;
  ;
  store into near/idata space
  ;
  mov     @r0, a                                   ;
  1
  dataptrrestore$:
  mov     r0, b   ;
  restore r0                     ;
  2
  ret                                             ;
  1
  ;
  ;
  cannot store into code space, lock up
  ;
  codeptr$:
  sjmp    .                                       ;
  2
  ;
  ;
  store into external stack/pdata space
  ;
  pdataptr$:
  movx    @r0, a                                   ;
  1
  sjmp    dataptrrestore$                         ;
  2
  ;
  ;
  store into far space, max 14 bits
  ;
  xdataptr$:
  ;
  0 <= dptr <= 0x3FFF
  movx    @dptr, a                                 ;
  1
  ret                                             ;
  1
  ;
  ===
  ;
  27 bytes
  __endasm;
}

#else

void
_gptrput( char *gptr, char c ) __naked {
  /* This is the new version with pointers up to 16 bits.
     B cannot be trashed */

  gptr;
  c; /* hush the compiler */

  __asm
  ;
  ;
  depending on the pointer type according to SDCCsymt.h
  ;
  jb      _B_7, codeptr$        ;
  >0x80 code       ;
  3
  jnb     _B_6, xdataptr$       ;
  <0x40 far        ;
  3

  mov     dph, r0 ;
  save r0 independant of regbank ;
  2
  mov     r0, dpl ;
  use only low order address     ;
  2

  jb      _B_5, pdataptr$       ;
  >0x60 pdata      ;
  3
  ;
  ;
  store into near/idata space
  ;
  mov     @r0, a                                   ;
  1
  dataptrrestore$:
  mov     r0, dph ;
  restore r0                     ;
  2
  mov     dph, #0 ; restore dph                    ; 2
  ret                                             ;
  1
  ;
  ;
  cannot store into code space, lock up
  ;
  codeptr$:
  sjmp    .                                       ;
  2
  ;
  ;
  store into external stack/pdata space
  ;
  pdataptr$:
  movx    @r0, a                                   ;
  1
  sjmp    dataptrrestore$                         ;
  2
  ;
  ;
  store into far space
  ;
  xdataptr$:
  movx    @dptr, a                                 ;
  1
  ret                                             ;
  1

  ;
  ===
  ;
  26 bytes
  __endasm;
}

#endif

#ifdef __SDCC_ds390

void
_gptrputWord( int *gptr, int w ) __naked {
  /* The ds390 can write two bytes in one go.
     B cannot be trashed */

  gptr;
  w; /* hush the compiler */

  __asm
  ;
  ;
  depending on the pointer type acc. to SDCCsymt.h
  ;
  jb      _B_7, codeptr_w$       ;
  >0x80 code
  jnb     _B_6, xdataptr_w$      ;
  <0x40 far

  mov     dph, r0 ;
  save r0 independant of regbank
  mov     r0, dpl ;
  use only low order address

  jb      _B_5, pdataptr_w$      ;
  >0x60 pdata
  ;
  ;
  store into near space
  ;
  mov     @r0, acc1
  inc     r0
  mov     @r0, a
  dataptrrestore_w$:
  mov     dpl, r0
  mov     r0, dph ;
  restore r0
  mov     dph, #0 ; restore dph
  ret
  ;
  ;
  cannot store into code space, lock up
  ;
  codeptr_w$:
  sjmp    .
  ;
  ;
  store into xstack space
  ;
  pdataptr_w$:
  xch     a, acc1
  movx    @r0, a
  inc     r0
  xch     a, acc1
  movx    @r0, a
  sjmp    dataptrrestore_w$
  ;
  ;
  store into far space
  ;
  xdataptr_w$:
  xch     a, acc1
  movx    @dptr, a
  inc     dptr
  xch     a, acc1
  movx    @dptr, a
  ret
  __endasm;
}

#endif
